import pandas as pd
from pandas import isna

from AsmExcel import AsmExcel
from Fy3dL2VsmHdf import Fy3dL2VsmHdf
from GenericExcel import GenericExcel
from GeoTiff import GeoTiff
from Timer import Timer
from utils import find_files, get_long_str


def combine_asm10_and_tvdi(asm10_path, tvdi_dir, save_path=None):
    timer = Timer()
    timer.tick(f"开始处理 {asm10_path}")
    asm10 = AsmExcel(asm10_path)
    col_name = 'hour_strs'
    hour_strs = asm10.append_col_timestr('%Y_%m_%d_%H', col_name)
    combined_data = []
    for hour_str in hour_strs:
        tvdi_paths = find_files(tvdi_dir, lambda f: f.upper().endswith('.TIF') and hour_str in f)
        for tvdi_path in tvdi_paths:
            timer.tick(f"{hour_str} 匹配到TVDI文件 {tvdi_path}")
            tvdi_tiff = GeoTiff(tvdi_path)
            rows = asm10.sub_rows(lambda r: r[col_name] == hour_str)
            for row in rows.itertuples(index=False, name=None):
                station_no, lat, lon, height, city, station_name, county, timestamp, vmc, srh, gwc, aws, _ = row
                tvdi_value = tvdi_tiff.get_pixel_value_interpolated(lat, lon)
                timer.tick(f"匹配 {station_name} 的TVDI观测值：{tvdi_value}")
                combined_data.append([station_no, station_name, lon, lat, hour_str, vmc, srh, gwc, aws, tvdi_value])
            timer.tick(f"{tvdi_path} 匹配完成")
            break
    columns = [AsmExcel.STATION_NO, AsmExcel.STATION_NAME, AsmExcel.LONGITUDE, AsmExcel.LATITUDE, '观测时间',
               AsmExcel.VWC, AsmExcel.SRH, AsmExcel.GWC, AsmExcel.AWS, 'TVDI']
    combined_df = pd.DataFrame(combined_data, columns=columns)
    if save_path:
        combined_df.to_excel(save_path, index=False)
    return combined_df


def combine_asm10_and_fy3dvsm(asm10_path, fy3dvsm_dir, save_path=None):
    timer = Timer()
    timer.tick(f"开始处理 {asm10_path}")
    asm10 = AsmExcel(asm10_path)
    col_name = 'date_strs'
    date_strs = asm10.append_col_timestr('%Y%m%d', col_name)
    combined_data = {}
    for date_str in date_strs:
        vsm_paths = find_files(fy3dvsm_dir, lambda f: f.upper().endswith('.HDF') and date_str in f)
        for vsm_path in vsm_paths:
            timer.tick(f"{date_str} 匹配到VSM文件 {vsm_path}")
            vsm_hdf = Fy3dL2VsmHdf(vsm_path)
            rows = asm10.sub_rows(lambda r: r[col_name] == date_str)
            for row in rows.itertuples(index=False, name=None):
                station_no, lat, lon, height, city, station_name, county, timestamp, vmc, srh, gwc, aws, _ = row
                key = f"{station_no}-{date_str}"
                if key in combined_data:
                    station_data = combined_data[key]
                else:
                    station_data = [station_no, station_name, lon, lat, date_str] + [float('nan')] * 10
                    combined_data[key] = station_data
                # 时间匹配：自动土壤水分观测站每小时记录一次测量值。卫星日产品是卫星过境时的瞬时观测值，由于卫星升降轨每天的过境时间固定，
                # 在河南省FY-3D升轨时间概在14点左右，降轨大概在凌晨3点左右，所以提取卫星升降轨过境时刻（14时、03时）对应的自动站小时数据，与卫星观测的日产品数据进行匹配。
                time_str = str(timestamp)
                if ' 03:' in time_str:
                    # vsm_d_value = vsm_hdf.vsm_d_at(lat, lon)
                    # 因测试数据质量糟糕，这里使用模拟值跑通流程
                    vsm_d_value = vsm_hdf.mock_vsm_d_at(lat, lon)
                    station_data[10:15] = vsm_d_value, vmc, srh, gwc, aws
                elif ' 14:' in time_str:
                    # vsm_a_value = vsm_hdf.vsm_a_at(lat, lon)
                    # 因测试数据质量糟糕，这里使用模拟值跑通流程
                    vsm_a_value = vsm_hdf.mock_vsm_d_at(lat, lon)
                    station_data[5:10] = vsm_a_value, vmc, srh, gwc, aws
            timer.tick(f"{vsm_path} 匹配完成")
            break
    columns = [AsmExcel.STATION_NO, AsmExcel.STATION_NAME, AsmExcel.LONGITUDE, AsmExcel.LATITUDE, '观测时间',
               'FY3D_A', 'VMC_14', 'SRH_14', 'GWC_14', 'AWS_14', 'FY3D_D', 'VMC_03', 'SRH_03', 'GWC_03', 'AWS_03']
    combined_df = pd.DataFrame(combined_data.values(), columns=columns)
    if save_path:
        combined_df.to_excel(save_path, index=False)
    return combined_df


def clean_asm10_vsm(asm10_vsm_path, save_path=None):
    asm10_vsm = GenericExcel(asm10_vsm_path)
    asm10_vsm.drop_rows(lambda r: isna(r['FY3D_A']) or isna(r['FY3D_D']))
    df = asm10_vsm.df
    df['FY3D_A-ASM_14'] = df['FY3D_A'] - df['VMC_14'] / 100
    df['abs_FY3D_A-ASM_14'] = abs(df['FY3D_A-ASM_14'])
    df['corr_FY3D_A-ASM_14'] = df['FY3D_A'].corr(df['VMC_14'])
    df['FY3D_D-ASM_03'] = df['FY3D_D'] - df['VMC_03'] / 100
    df['abs_FY3D_D-ASM_03'] = abs(df['FY3D_D-ASM_03'])
    df['corr_FY3D_D-ASM_03'] = df['FY3D_D'].corr(df['VMC_03'])
    if save_path:
        df.to_excel(save_path, index=False)
    return df


def concat_asm10_vsm_files(asm10_vsm_files, save_path=None):
    combined_df = pd.DataFrame()
    for asm10_vsm_file in asm10_vsm_files:
        df = pd.read_excel(asm10_vsm_file)
        combined_df = pd.concat([combined_df, df], ignore_index=True)
    if save_path:
        combined_df.to_excel(save_path, index=False)
    return combined_df


def analyse_asm10_vsm_com(asm10_vsm_com_file_path, result_save_path=None):
    whole_df = pd.read_excel(asm10_vsm_com_file_path)
    sub_dfs = {"全部": whole_df}
    # 将 '观测时间' 列转换为字符串类型
    whole_df['观测时间'] = whole_df['观测时间'].astype(str)
    whole_df['年份'] = whole_df['观测时间'].str[:4]
    whole_df['月份'] = whole_df['观测时间'].str[:6]
    y_dfs = whole_df.groupby('年份')
    for name, sub_df in y_dfs:
        sub_dfs[name] = sub_df
    m_dfs = whole_df.groupby('月份')
    for name, sub_df in m_dfs:
        sub_dfs[name] = sub_df

    columns = ['统计内容', 'A平均误差', 'A平均绝对误差', 'A误差>=0个数', 'A误差<0个数', 'A平均相关系数', 'A误差在10%以上的站点', 'A误差在5%以下的站点',
               'D平均误差', 'D平均绝对误差', 'D误差>=0个数', 'D误差<0个数', 'D平均相关系数', 'D误差在10%以上的站点', 'D误差在5%以下的站点']
    result_df = pd.DataFrame(columns=columns)
    for name, sub_df in sub_dfs.items():
        a_me_mean_value = sub_df['FY3D_A-ASM_14'].mean()
        a_mae_mean_value = sub_df['abs_FY3D_A-ASM_14'].mean()
        a_me_gt0_count = (sub_df['FY3D_A-ASM_14'] > 0).sum()
        a_me_lt0_count = (sub_df['FY3D_A-ASM_14'] < 0).sum()
        a_corr_mean_value = sub_df['corr_FY3D_A-ASM_14'].mean()
        sub_df['a_maep'] = abs(sub_df['FY3D_A-ASM_14'] / sub_df['VMC_14'])
        a_maep_gt10_list = get_long_str(sub_df, lambda r: r['a_maep'] > .1, lambda r: r[AsmExcel.STATION_NAME])
        a_maep_lt5_list = get_long_str(sub_df, lambda r: r['a_maep'] < .05, lambda r: r[AsmExcel.STATION_NAME])
        d_me_mean_value = sub_df['FY3D_D-ASM_03'].mean()
        d_mae_mean_value = sub_df['abs_FY3D_D-ASM_03'].mean()
        d_me_gt0_count = (sub_df['FY3D_D-ASM_03'] >= 0).sum()
        d_me_lt0_count = (sub_df['FY3D_D-ASM_03'] < 0).sum()
        d_corr_mean_value = sub_df['corr_FY3D_D-ASM_03'].mean()
        sub_df['d_maep'] = abs(sub_df['FY3D_D-ASM_03'] / sub_df['VMC_03'])
        d_maep_gt10_list = get_long_str(sub_df, lambda r: r['d_maep'] > .1, lambda r: r[AsmExcel.STATION_NAME])
        d_maep_lt5_list = get_long_str(sub_df, lambda r: r['d_maep'] < .05, lambda r: r[AsmExcel.STATION_NAME])
        row = (name, a_me_mean_value, a_mae_mean_value, a_me_gt0_count, a_me_lt0_count, a_corr_mean_value, a_maep_gt10_list, a_maep_lt5_list,
               d_me_mean_value, d_mae_mean_value, d_me_gt0_count, d_me_lt0_count, d_corr_mean_value, d_maep_gt10_list, d_maep_lt5_list)
        result_df.loc[len(result_df)] = row

    if result_save_path:
        result_df.to_excel(result_save_path, index=False)
    return result_df
